package com.oracle2mysql.migration;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Oracle函数到MySQL函数的映射处理器
 */
public class FunctionMapper {
    
    private static final Logger logger = LoggerFactory.getLogger(FunctionMapper.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    // 函数映射表
    private Map<String, String> functionMap = new HashMap<>();
    
    /**
     * 构造函数 - 用于传统方式
     */
    public FunctionMapper(Properties config) {
        initDefaultMappings();
        loadCustomMappings(config);
    }
    
    /**
     * 构造函数 - 支持从JSON文件加载函数映射
     */
    public FunctionMapper(Properties config, String functionMappingFile) {
        initDefaultMappings();
        loadCustomMappings(config);
        
        // 从JSON文件加载函数映射
        if (functionMappingFile != null && !functionMappingFile.isEmpty()) {
            try {
                loadFromJsonFile(functionMappingFile);
            } catch (IOException e) {
                logger.error("加载函数映射JSON文件失败: {}", e.getMessage(), e);
            }
        }
    }
    
    /**
     * 初始化默认的函数映射关系
     */
    private void initDefaultMappings() {
        // 默认映射会在JSON文件中定义，这里保留基础映射作为后备
        functionMap.put("NVL", "IFNULL");
        functionMap.put("NVL2", "IF");
        functionMap.put("TO_CHAR", "CAST");
        functionMap.put("SYSDATE", "NOW()");
        functionMap.put("LISTAGG", "GROUP_CONCAT");
        functionMap.put("ROWNUM", "LIMIT");
    }
    
    /**
     * 加载自定义的函数映射关系
     */
    private void loadCustomMappings(Properties config) {
        // 从配置文件中加载自定义映射
        for (String key : config.stringPropertyNames()) {
            if (key.startsWith("function.map.")) {
                String oracleFunc = key.substring("function.map.".length());
                String mysqlFunc = config.getProperty(key);
                functionMap.put(oracleFunc, mysqlFunc);
            }
        }
    }
    
    /**
     * 从JSON文件加载函数映射
     */
    @SuppressWarnings("unchecked")
    private void loadFromJsonFile(String functionMappingFile) throws IOException {
        Map<String, Object> jsonData;
        
        // 处理classpath路径
        if (functionMappingFile.startsWith("classpath:")) {
            String resourcePath = functionMappingFile.substring("classpath:".length());
            try (InputStream is = FunctionMapper.class.getClassLoader().getResourceAsStream(resourcePath)) {
                if (is != null) {
                    jsonData = objectMapper.readValue(is, Map.class);
                    logger.info("已从classpath加载函数映射文件: {}", resourcePath);
                } else {
                    logger.warn("在classpath中找不到函数映射文件: {}", resourcePath);
                    return;
                }
            }
        } else {
            // 处理文件系统路径
            File file = new File(functionMappingFile);
            if (file.exists()) {
                jsonData = objectMapper.readValue(file, Map.class);
                logger.info("已从文件系统加载函数映射文件: {}", functionMappingFile);
            } else {
                logger.warn("函数映射文件不存在: {}", functionMappingFile);
                return;
            }
        }
        
        // 加载函数映射
        if (jsonData.containsKey("functionMappings")) {
            Object mappingsObj = jsonData.get("functionMappings");
            if (mappingsObj instanceof Map) {
                Map<?, ?> mappings = (Map<?, ?>) mappingsObj;
                for (Map.Entry<?, ?> entry : mappings.entrySet()) {
                    if (entry.getKey() instanceof String && entry.getValue() instanceof Map) {
                        String oracleFunc = ((String) entry.getKey()).toUpperCase();
                        Map<?, ?> functionDetails = (Map<?, ?>) entry.getValue();
                        if (functionDetails.containsKey("mysqlFunction") && functionDetails.get("mysqlFunction") instanceof String) {
                            String mysqlFunc = (String) functionDetails.get("mysqlFunction");
                            functionMap.put(oracleFunc, mysqlFunc);
                        }
                    }
                }
                logger.info("已加载 {} 个函数映射", mappings.size());
            }
        }
        
        // 加载数据类型映射
        if (jsonData.containsKey("dataTypeMappings")) {
            Object typeMappingsObj = jsonData.get("dataTypeMappings");
            if (typeMappingsObj instanceof Map) {
                Map<?, ?> typeMappings = (Map<?, ?>) typeMappingsObj;
                for (Map.Entry<?, ?> entry : typeMappings.entrySet()) {
                    if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
                        String oracleType = ((String) entry.getKey()).toUpperCase();
                        String mysqlType = (String) entry.getValue();
                        functionMap.put("TYPE:" + oracleType, mysqlType);
                    }
                }
                logger.info("已加载 {} 个数据类型映射", typeMappings.size());
            }
        }
    }
    
    /**
     * 获取Oracle函数对应的MySQL函数
     */
    public String getMysqlFunction(String oracleFunction) {
        if (oracleFunction == null) {
            return null;
        }
        return functionMap.get(oracleFunction.toUpperCase());
    }
    
    /**
     * 检查是否包含指定的Oracle函数
     */
    public boolean containsFunction(String oracleFunction) {
        if (oracleFunction == null) {
            return false;
        }
        return functionMap.containsKey(oracleFunction.toUpperCase());
    }
    
    /**
     * 添加或更新函数映射
     */
    public void addMapping(String oracleFunction, String mysqlFunction) {
        functionMap.put(oracleFunction.toUpperCase(), mysqlFunction);
    }
    
    /**
     * 获取函数映射表
     */
    public Map<String, String> getFunctionMap() {
        return functionMap;
    }
}